package apig.servlet;

import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.zip.*;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.*;
import org.apache.commons.fileupload.servlet.*;

import apig.client.*;
import apig.client.serviface.*;
import apig.core.*;

public class ZipUploadServlet extends HttpServlet {
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		UserData ud = null;
		int labId = Integer.parseInt(request.getParameter(Stubman.LAB_ID));
		try {
			ud = ApigServiceImpl.getUserData(request.getSession(true).getId());
			if ((ud.sessionId == null) || !ud.logged
					|| (ud.role != UserData.ROLE_STUD)) {
				throw new ServletException("Unauthorized");
			}
		} catch (SQLException ex) {
			throw new ServletException(ex);
		}

		try {
			DiskFileItemFactory factory = new DiskFileItemFactory();
			factory.setSizeThreshold(1024 * 1024);
			ServletFileUpload upload = new ServletFileUpload(factory);
			upload.setSizeMax(1024 * 1024 * 10);
			List<FileItem> items = upload.parseRequest(request);
			Iterator<FileItem> i = items.iterator();

			if (i.hasNext()) {
				FileItem item = (FileItem) i.next();
				if (!item.isFormField()) {
					try (Connection c = ServerThings.getThings()
							.getConnection();) {
						int newRevision = getRevi(labId, ud.userId, c);
						addIntoDB(item, labId, ud.userId, newRevision, c);
					} catch (SQLException ex) {
						;
					}
				}
			}

		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	private int getRevi(int labId, int userId, Connection c) {

		int newRevision;

		try (PreparedStatement reviStat = c
				.prepareStatement("select max(codes.revision) from codes, labs where "
						+ "codes.lab_id = ? and codes.user_id = ?");) {
			reviStat.setInt(1, labId);
			reviStat.setInt(2, userId);
			ResultSet reviRS = reviStat.executeQuery();
			reviRS.next();
			newRevision = reviRS.getInt(1);
			newRevision++;
		} catch (SQLException ex) {
			System.out.println("ex: " + ex.getMessage());
			System.out.println("revi: " + -1);
			return -1;
		}

		System.out.println("revi: " + newRevision);

		return newRevision;
	}

	private void addIntoDB(FileItem item, int labId, int userId,
			int newRevision, Connection c) {

		try (InputStream in = item.getInputStream();

				PreparedStatement insertStat = c.prepareStatement(""
						+ "insert into codes values "
						+ "(codes.nextval, ?, ?, ?, ?, ?, "
						+ "CURRENT_TIMESTAMP, false);");) {

			ZipInputStream zin = new ZipInputStream(in);
			ZipEntry zEntry;

			while ((zEntry = zin.getNextEntry()) != null) {

				// extract code
				ByteArrayOutputStream bout = new ByteArrayOutputStream();
				write(zin, bout);
				String code = new String(bout.toByteArray());

				insertStat.setInt(1, labId);
				insertStat.setInt(2, userId);
				insertStat.setInt(3, newRevision);
				insertStat.setString(4, zEntry.getName());
				insertStat.setString(5, code);
				insertStat.executeUpdate();

			}
			c.commit();
			AlgoRunManager.getManager().run();
		} catch (IOException | SQLException ex) {
			System.out.println("ne zip file :)");
			ex.printStackTrace();
		}

	}

	private static final void write(InputStream in, OutputStream out)
			throws IOException {
		byte[] buffer = new byte[1000];
		int length;
		while ((length = in.read(buffer)) >= 0) {
			out.write(buffer, 0, length);
		}
	}
}

// /**
// *
// * @author evgeniy
// *
// */
// public class ZipUploadServlet extends HttpServlet {
//
// private static final long serialVersionUID = 1L;
//
// public static final String BUNDLE_ID = "bundle_id";
//
// public static final int NO_BUNDLE = -1;
//
// /**
// * @see HttpServlet#HttpServlet()
// */
// public ZipUploadServlet() {
// super();
// }
//
// /**
// * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
// * response)
// */
// protected void doGet(HttpServletRequest request,
// HttpServletResponse response) throws ServletException, IOException {
// // TODO:
// }
//
// /**
// * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
// * response)
// */
// protected void doPost(HttpServletRequest request,
// HttpServletResponse response) throws ServletException, IOException {
// try {
// UserData urd = UserServiceImpl.getUserData(request.getSession(true)
// .getId());
// if ((urd.sessionId == null) || !urd.logged
// || (urd.role != UserData.ROLE_STUD)) {
// throw new ServletException("Unauthorized");
// } else {
// String bundleIdString;
//
// int labId = (Integer) request.getAttribute(Stubman.LAB_ID);
//
// boolean isMultipart = ServletFileUpload
// .isMultipartContent(request);
// if (isMultipart) {
// DiskFileItemFactory factory = new DiskFileItemFactory();
// factory.setSizeThreshold(1024 * 1024);
// ServletFileUpload upload = new ServletFileUpload(factory);
// upload.setSizeMax(1024 * 1024 * 10);
//
//
//
//
//
// } else {
// request.getRequestDispatcher("/illegal").forward(request,
// response);
// }
// }
// } catch (SQLException ex) {
// throw new ServletException(ex);
// }
// }
//
// // private void showBundleDiff(HttpServletRequest request,
// // HttpServletResponse response, int bundleId, int labId, int discId,
// // UserRequesterData urd) throws ServletException, SQLException,
// // IOException {
// //
// // String zipUploadHandlerName = ServletUtils.PREFIX + "/stud/"
// // + StudRootServlet.ALL_DISCIPLINES + "/"
// // + ServletUtils.getDisciplineURLElement(discId) + "/"
// // + ServletUtils.getLabURLElement(labId) + "/"
// // + StudRootServlet.UPLOAD_ZIP;
// //
// // Connection c = ServerThings.getThings().getConnection();
// // // TODO: пока что показывается просто список файлов, но потом надо
// // // реализовать показ
// // // diff-а по файлам
// // PreparedStatement s = c
// //
// .prepareStatement("SELECT apii.upload_codes.name, length(apii.upload_codes.code) "
// // + "FROM apii.upload_codes "
// // + "WHERE apii.upload_codes.upload_code_bundle_id = ?");
// // s.setInt(1, bundleId);
// // ResultSet codesToPostRS = s.executeQuery();
// //
// // PrintWriter pw = response.getWriter();
// // ServletUtils.startCommonStudDoc(pw, urd, "Загрузка кода");
// // pw.println("<table border =\"1\">");
// // pw.println("<tr>");
// // pw.println("<td><b>Файлы, которые Вы загружаете</b></td>");
// // pw.println("<td><b>Размер</b></td>");
// // pw.println("</tr>");
// // while (codesToPostRS.next()) {
// // pw.println("<tr>");
// // pw.println("<td>" + codesToPostRS.getString(1) + "</td>");
// // pw.println("<td>" + sizeToString(codesToPostRS.getInt(2)) + "</td>");
// // pw.println("</tr>");
// // }
// // pw.println("</table>");
// // ServletUtils.closeCommonStudDoc(pw, urd);
// // c.close();
// // pw.println("<form action=\"" + zipUploadHandlerName + "?" + BUNDLE_ID
// // + "=" + bundleId + "\" method=\"post\" "
// // + "enctype=\"multipart/form-data\">");
// // pw.println("<input type=\"submit\" value=\"Подтвердить\"><br>");
// // pw.println("</form>");
// // }
//
// private int addIntoDB(FileItem item, int userId) throws Exception {
// InputStream in = item.getInputStream();
// int bundleId = NO_BUNDLE;
//
// try (Connection c = ServerThings.getThings().getConnection();) {
//
// ZipInputStream zin = new ZipInputStream(in);
// ZipEntry zEntry;
// boolean bundleEntryCreated = false;
//
// while ((zEntry = zin.getNextEntry()) != null) {
//
// // extract code
// ByteArrayOutputStream bout = new ByteArrayOutputStream();
// write(zin, bout);
// String code = new String(bout.toByteArray());
//
// // put temporarily the code to the db:
// if (!bundleEntryCreated) {
// bundleEntryCreated = true;
// bundleId = createBundleEntry(c, userId);
// }
//
// PreparedStatement s = c
// .prepareStatement("INSERT INTO apii.upload_codes VALUES (?, ?, ?);");
// s.setString(1, code);
// s.setString(2, zEntry.getName());
// s.setInt(3, bundleId);
// s.executeUpdate();
//
// // System.out.println("executing update ..." + s.toString());
// // System.out
// // .println("archive size: " + bout.toByteArray().length);
// }
// c.commit();
// in.close();
// } catch (IOException | SQLException ex) {
// System.out.println("ne zip file :)");
// ex.printStackTrace();
// }
//
// return bundleId;
// }
//
// private static final boolean commitBundle(int bundleId, int labId,
// UserData urd) throws SQLException {
// boolean result;
// try (Connection c = ServerThings.getThings().getConnection()) {
// // check that the is the correct id
// PreparedStatement checkStatement = c
// .prepareStatement("SELECT apii.upload_code_bundles.user_id "
// + "FROM apii.upload_code_bundles "
// + "WHERE apii.upload_code_bundles.upload_code_bundle_id = ?");
// checkStatement.setInt(1, bundleId);
// ResultSet checkRS = checkStatement.executeQuery();
// if (checkRS.next()) {
// int userId = checkRS.getInt(1);
// if (userId != urd.userId) {
// result = false;
// } else {
// PreparedStatement commitStatement = c
// .prepareStatement("INSERT INTO codes VALUES "
// + "(?, " + "?, ?, ?, ?, ?, "
// + "'2011-11-15 15:05:35', false);");
// commitStatement.setInt(2, labId);
// commitStatement.setInt(3, userId);
//
// PreparedStatement codesFromBundleStatement = c
// .prepareStatement("SELECT apii.upload_codes.name, "
// + "apii.upload_codes.code "
// + "FROM apii.upload_codes "
// + "WHERE apii.upload_codes.upload_code_bundle_id = ?");
// codesFromBundleStatement.setInt(1, bundleId);
// ResultSet codesFromBundleRS = codesFromBundleStatement
// .executeQuery();
//
// Statement revisionStatement = c.createStatement();
// // lock db
// ResultSet codeLockRS = revisionStatement
// .executeQuery("SELECT apii.codes.revision FROM apii.codes "
// + "WHERE apii.codes.lab_id = '"
// + labId
// + "' AND apii.codes.user_id = '"
// + userId
// + "' FOR UPDATE");
// int revision = 1;
// if (codeLockRS.next()) {
// Statement s = c.createStatement();
// ResultSet maxRevisionRS = s
// .executeQuery("SELECT max(apii.codes.revision) FROM apii.codes "
// + "WHERE apii.codes.lab_id = '"
// + labId
// + "' AND apii.codes.user_id = '"
// + userId + "'");
// maxRevisionRS.next();
// revision = maxRevisionRS.getInt(1) + 1;
// }
// commitStatement.setInt(4, revision);
// PreparedStatement codeIdStatement = c
// .prepareStatement("SELECT nextval('codes')");
// List<Integer> codeIds = new ArrayList<Integer>();
// while (codesFromBundleRS.next()) {
// ResultSet codeIdRS = codeIdStatement.executeQuery();
// codeIdRS.next();
// int codeId = codeIdRS.getInt(1);
// codeIds.add(codeId);
// commitStatement.setInt(1, codeId);
// commitStatement.setString(5,
// codesFromBundleRS.getString(1));
// commitStatement.setString(6,
// codesFromBundleRS.getString(2));
// commitStatement.executeUpdate();
// }
// // TODO: temporary! remove this later
// AlgoRunManager.getManager();
// c.commit();
// c.close();
// for (Integer codeId : codeIds) {
// AlgoRunManager.getManager().runCodeLabour(codeId);
// }
// result = true;
// }
// } else {
// result = false;
// }
// checkStatement.close();
// }
//
// return result;
// }
//
// private static final String sizeToString(int size) {
// double sizeInKb = size / (1024.0);
// return String.format("%.1fKB", sizeInKb);
// }
//
// private static final int createBundleEntry(Connection c, int userId)
// throws SQLException {
// // TODO: make prepared statement
// // TODO: make good timestamp
// Statement getIdStatement = c.createStatement();
// ResultSet nextvalRS = getIdStatement
// .executeQuery("SELECT nextval('apii.upload_code_bundles')");
// if (!nextvalRS.next()) {
// throw new Error();
// }
// int bundleId = nextvalRS.getInt(1);
// PreparedStatement insertStatement = c
// .prepareStatement("INSERT INTO upload_code_bundles VALUES (?, ?)");
// insertStatement.setInt(1, bundleId);
// insertStatement.setInt(2, userId);
// insertStatement.executeUpdate();
//
// return bundleId;
// }
//
// private static final void write(InputStream in, OutputStream out)
// throws IOException {
// byte[] buffer = new byte[1000];
// int length;
// while ((length = in.read(buffer)) >= 0) {
// out.write(buffer, 0, length);
// }
// }
// }
